package com.wm.blog_admin.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wm.blog_admin.controller.resp.IconExportResp;
import com.wm.blog_admin.controller.resp.TagExportResp;
import com.wm.blog_admin.dao.TTagDAO;
import com.wm.blog_admin.feign.PictureFeignClient;
import com.wm.blog_admin.query.TIconQuery;
import com.wm.blog_admin.query.TTagQuery;
import com.wm.blog_admin.task.IconThreadTask;
import com.wm.blog_admin.task.TagThreadTask;
import com.wm.blog_common.base.BeanUtils;
import com.wm.blog_common.bean.PageHelper;
import com.wm.blog_common.bean.QueryPage;
import com.wm.blog_common.constatnt.CommonConstant;
import com.wm.blog_common.constatnt.ErrorConstant;
import com.wm.blog_common.domain.TFileDO;
import com.wm.blog_common.domain.TIconDO;
import com.wm.blog_common.domain.TTagDO;
import com.wm.blog_common.entity.TFile;
import com.wm.blog_common.entity.TTag;
import com.wm.blog_common.exception.BusinessException;
import com.wm.blog_common.result.Result;
import com.wm.blog_common.util.CommonUtil;
import com.wm.blog_common.util.StringUtil;
import com.wm.blog_common.util.excel.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * <p>
 * 标签表 服务实现类
 * </p>
 *
 * @author wm_yu
 * @since 2020-03-24
 */
@Service
@Slf4j
public class TTagService{
    @Autowired
    private TTagDAO tTagDAO;

    @Autowired
    private PictureFeignClient pictureFeignClient;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 根据ID查询
     * @param id
     * @return
     */
    public Result<TTagDO> selectById(Long id){
        return Result.success(BeanUtils.copyProperties(tTagDAO.getById(id),TTagDO.class));
    }

    /**
    * 根据ID删除
    * @param id
    * @return
    */
    public Result deleteById(Long id){
        return tTagDAO.removeById(id)?Result.success():Result.failure();
    }

    /**
    * 添加
    * @param tTag
    * @return
    */
    public Result insert(TTag tTag){
        return tTagDAO.save(tTag)?Result.success():Result.failure();
    }

    /**
    * 修改
    * @param tTag
    * @return
    */
    public Result update(TTag tTag){
        return tTagDAO.updateById(tTag)?Result.success():Result.failure();
    }

    /**
    * 统计总数
    *
    * @param query
    * @return
    */
    public Result<Integer> count(TTagQuery query) {
        return Result.success(tTagDAO.count(this.combineQuery(query)));
    }

    /**
    * 列表查询
    * @param query
    * @return
    */
    public Result<List<TTagDO>> list(TTagQuery query){
        return Result.success(BeanUtils.copyListProperties(tTagDAO.list(this.combineQuery(query)),TTagDO.class));
    }
    /**
    * 分页查询
    * @param page
    * @return
    */
    public Result<Page<TTagDO>> page(QueryPage page, TTagQuery query){
        Page<TTagDO> doPage = PageHelper.newPage(tTagDAO.page(page, this.combineQuery(query)), TTagDO.class);
        if(!ObjectUtils.isEmpty(doPage) && !CollectionUtils.isEmpty(doPage.getRecords())){
            List<Long> picIdList = doPage
                    .getRecords()
                    .stream()
                    .map(TTagDO::getFileId)
                    .distinct()
                    .collect(Collectors.toList());

            if(!CollectionUtils.isEmpty(picIdList)){
                // k：id v:url
                Map<Long, String> map = Optional
                        .ofNullable(pictureFeignClient.getByIdList(picIdList).getData())
                        .orElse(Collections.emptyList())
                        .stream()
                        .collect(Collectors.toMap(TFile::getId, TFile::getPicUrl));
                doPage.getRecords().forEach(item -> {
                    item.setAvatar(map.getOrDefault(item.getFileId(),null));
                });
            }
        }
        return Result.success(doPage);
    }

    /**
    * 组装查询条件
    *
    * @param query
    * @return
    */
    private QueryWrapper<TTag> combineQuery(TTagQuery query) {
        QueryWrapper<TTag> wrapper = new QueryWrapper<>();
        Optional.ofNullable(query).ifPresent(item -> {
            Optional.ofNullable(query.getStatus()).ifPresent(x -> {
                wrapper.eq("status",x);
            });
            Optional.ofNullable(query.getContent()).filter(StringUtil::isNotEmpty).ifPresent(x -> {
                wrapper.like("content",x);
            });
        });
        return wrapper;
    }


    /**
     * excel导出
     * @param query
     * @param response
     */
    public void export(TTagQuery query, HttpServletResponse response) {
        query = Optional.ofNullable(query).orElse(new TTagQuery());
        //使用多线程查询
        Integer current = 1;
        Integer size = 1;
        QueryPage page = new QueryPage(current, size);
        Result<Page<TTagDO>> result = this.page(page, query);
        if(result.isSuccess()){
            Long total = result.getData().getTotal();
            if(total > 0){
                //计算需要的线程数量
                Integer threadCount = CommonUtil.getThreadCount(total.intValue());
                List<Future<List<TagExportResp>>> futureList = new ArrayList<>();
                for (Integer i = 1; i <= threadCount; i++) {
                    //构建多线程请求入参
                    Future<List<TagExportResp>> future = threadPoolTaskExecutor.submit(new TagThreadTask(i, CommonConstant.DEFAULT_MAX_SIZE, this, query));
                    futureList.add(future);
                }
                //处理线程结果
                if(!CollectionUtils.isEmpty(futureList)){
                    List<TagExportResp> respList = new ArrayList<>();
                    for (Future<List<TagExportResp>> future : futureList) {
                        try {
                            respList.addAll(future.get());
                        } catch (InterruptedException | ExecutionException e) {
                            log.error("线程获取数据失败:[{}]",e.getMessage(),e);
                            //取消当前任务
                            future.cancel(true);
                        }
                    }
                    //导出excel
                    List<String> headerList = CommonUtil.getExcelHeaderList(TagExportResp.class);
                    String title = CommonConstant.ICON_EXPORT_TITLE;
                    ExcelUtil.downloadExcelFile(title,headerList,respList,response);
                }
            }
        }
    }

    /**
     * 详情查询
     * @param id
     * @return
     */
    public Result getDetail(Long id) {
        Optional.ofNullable(id).orElseThrow(() -> new BusinessException(ErrorConstant.BLOG_TAG_ID_EMPTY));
        TTag tag = Optional.ofNullable(tTagDAO.getById(id)).orElse(new TTag());
        TTagDO tagDO = Optional.ofNullable(BeanUtils.copyProperties(tag, TTagDO.class)).orElse(new TTagDO());
        if(!ObjectUtils.isEmpty(tagDO.getFileId())){
            String picUrl = Optional.ofNullable(pictureFeignClient.get(tagDO.getId()).getData()).orElse(new TFileDO()).getPicUrl();
            tagDO.setAvatar(picUrl);
        }
        return Result.success(tagDO);
    }
}







